/*
 * Copyright (c) GoKeep by gokeep.org. 2022-2023. All rights reserved
 */
package org.gokeep.communication.engine;

import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.gokeep.common.component.SessionCacheComponent;
import org.gokeep.communication.event.Event;
import org.gokeep.communication.proto.MessageProto;
import org.gokeep.communication.util.MessageVerify;
import org.smartboot.socket.StateMachineEnum;
import org.smartboot.socket.extension.processor.AbstractMessageProcessor;
import org.smartboot.socket.transport.AioSession;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * TCP消息处理
 */
@Slf4j
@Component
public class CommunicationMessageProcess extends AbstractMessageProcessor<MessageProto.Message> {
    @Resource
    private List<Event> events;

    @Resource
    private MessageVerify messageVerify;

    @Resource
    private SessionCacheComponent sessionCacheComponent;
    /**
     * 状态事件通知接口
     * @param session
     * @param stateMachineEnum
     * @param throwable
     */
    @Override
    public void stateEvent0(AioSession session, StateMachineEnum stateMachineEnum, Throwable throwable) {
        String sessionId = session.getSessionID();
        if (throwable != null) {
            throwable.printStackTrace();
        }
        switch (stateMachineEnum) {
            case NEW_SESSION -> // 根据获取到的auth信息校验权限，缺人是否需要建立连接
                    log.info("First connect session id is: [{}]", sessionId);
            case SESSION_CLOSED -> {
                tryClearResource(sessionId);
                log.info("Client disconnect sessionId: {}", session.getSessionID());
            }
            default -> {
                //此处以后可能会做细节化异常处理
                tryClearResource(sessionId);
                log.warn("Session status is: {}, and not resolve", stateMachineEnum);
            }
        }
    }

    /**
     * 正式处理程序
     * @param session
     * @param receiveMessage
     */
    @Override
    @SneakyThrows
    public void process0(AioSession session, MessageProto.Message receiveMessage) {
        log.info("Process[{}] -> command: {}]", session.getSessionID(), receiveMessage.getCommand());
        if (!messageVerify.verify(receiveMessage)) {
            log.warn("Token verify not pass, token is : {}", receiveMessage.getToken());
            tryClearResource(session.getSessionID());
        }
        events.forEach(event -> event.execute(session, receiveMessage));
    }

    /**
     * 尝试清理资源
     * @param sessionId
     */
    private void tryClearResource(String sessionId) {
        sessionCacheComponent.closeAndRemoveLocalUserAioSession(sessionId);
    }
}